package com.sina.finance.commons.security;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.security.Key;
import java.util.Properties;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.core.io.Resource;
import org.springframework.util.DefaultPropertiesPersister;
import org.springframework.util.PropertiesPersister;
public class DecryptPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
	private static Logger logger = LoggerFactory.getLogger(DecryptPropertyPlaceholderConfigurer.class);
	private Resource[] locations;         
	private Resource keyLocation;     
	private String fileEncoding; 
	public void setLocations(Resource[] locations){ 
		try {
			  this.locations = locations;  
		} catch (Exception e) {
			e.printStackTrace();
		}
	     
	} 
	public void setKeyLocation(Resource keyLocation){ 
		try {
			  this.keyLocation = keyLocation;   
		} catch (Exception e) {
			e.printStackTrace();
		}
	   
	}    	
	public void setFileEncoding(String fileEncoding) {
		this.fileEncoding = fileEncoding;
	}
	public void loadProperties(Properties props) throws IOException{ 
        if (this.locations != null){            
		    PropertiesPersister propertiesPersister = new DefaultPropertiesPersister();             
			for (int i = 0; i < this.locations.length; i++)             {                 
				Resource location = this.locations[i];                 
				if (logger.isInfoEnabled()){                     
				    logger.info("Loading properties file from " + location);                
				}                 
				InputStream is = null;                 
				try{                     
					is = location.getInputStream();                     
					Key key =getKey(keyLocation.getInputStream());                   
					is =doDecrypt(key, location.getFile());                     
					if (fileEncoding != null){                        
						propertiesPersister.load(props, new InputStreamReader(                               
						is, fileEncoding));                    
					}else{                         
					    propertiesPersister.load(props, is);                    
				    } 
				}             
				finally{                   
					if (is != null){                        
					   is.close();                    
					}                
				}          
			}         
	    }    
	} 
	/**      
	* <ul>     
	* <li>Description:[根据流得到密钥]</li>    
	* <li>Created by [Huyvanpull] [Jul 19, 2010]</li>      
	* <li>Midified by [修改人] [修改时间]</li>      
	* </ul>      
	*      
	* @param is      
	* @return      
	*/    
	public static Key getKey(InputStream is){         
		try{             
			ObjectInputStream ois = new ObjectInputStream(is);    
			return (Key) ois.readObject();         
		}catch (Exception e){          
			e.printStackTrace();             
			throw new RuntimeException(e);        
		}     
	} 
	
	/**      
	* <ul>     
	* <li>Description:[对数据进行解密]</li>      
	* <li>Created by [Huyvanpull] [Jul 19, 2010]</li>      
	* <li>Midified by [修改人] [修改时间]</li>     
	* </ul>     
	*       
	* @param key      
	* @param in     
	* @return    
	*/   
	public static InputStream doDecrypt(Key key, File file){         
		try{       
			Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");         
			// build the initialization vector. This example is all zeros, but it
			// could be any value or generated using a random number generator.
			byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0 };
			IvParameterSpec ivspec = new IvParameterSpec(iv);
			cipher.init(Cipher.DECRYPT_MODE, key, ivspec);
			String base64secretText = FileUtils.readFileToString(file,"UTF-8");
			logger.info(">>> base64secretText:{}",base64secretText);
			byte[] raw = cipher.doFinal(Base64Utils.decode(base64secretText));         
			ByteArrayInputStream bin = new ByteArrayInputStream(raw);        
			return bin;
		}catch (Exception e){          
			e.printStackTrace();        
			throw new RuntimeException(e); 
		        
		}     
	}   
}
